home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / EXTRALEV.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  11KB  |  390 lines

  1. /*    SCCS Id: @(#)extralev.c    3.0    88/04/11            */
  2. /*    Copyright 1988, 1989 by Ken Arromdee                */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #define MONATTK_H    /* comment line for pre-compiled headers */
  6. /* block some unused #defines to avoid overloading some cpp's */
  7. #include "hack.h"
  8.  
  9. #ifdef REINCARNATION
  10.  
  11. struct rogueroom {
  12.     xchar rlx, rly;
  13.     xchar dx, dy;
  14.     boolean real;
  15.     uchar doortable;
  16.     int nroom; /* Only meaningful for "real" rooms */
  17. };
  18. #define UP 1
  19. #define DOWN 2
  20. #define LEFT 4
  21. #define RIGHT 8
  22.  
  23. static struct rogueroom NEARDATA r[3][3];
  24. static void FDECL(roguejoin,(int,int,int,int,int));
  25. static void FDECL(roguecorr,(int,int,int));
  26. static void FDECL(miniwalk,(int,int));
  27.  
  28. static
  29. void
  30. roguejoin(x1,y1,x2,y2, horiz)
  31. int x1,y1,x2,y2;
  32. int horiz;
  33. {
  34.     register int x,y,middle;
  35. #ifndef MAX
  36. #define MAX(a,b) (((a) > (b)) ? (a) : (b))
  37. #endif
  38. #ifndef MIN
  39. #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  40. #endif
  41.     if (horiz) {
  42.         middle = x1 + rn2(x2-x1+1);
  43.         for(x=MIN(x1,middle); x<=MAX(x1,middle); x++)
  44.             corr(x, y1);
  45.         for(y=MIN(y1,y2); y<=MAX(y1,y2); y++)
  46.             corr(middle,y);
  47.         for(x=MIN(middle,x2); x<=MAX(middle,x2); x++)
  48.             corr(x, y2);
  49.     } else {
  50.         middle = y1 + rn2(y2-y1+1);
  51.         for(y=MIN(y1,middle); y<=MAX(y1,middle); y++)
  52.             corr(x1, y);
  53.         for(x=MIN(x1,x2); x<=MAX(x1,x2); x++)
  54.             corr(x, middle);
  55.         for(y=MIN(middle,y2); y<=MAX(middle,y2); y++)
  56.             corr(x2,y);
  57.     }
  58. }
  59.  
  60. static
  61. void
  62. roguecorr(x, y, dir)
  63. int x,y,dir;
  64. {
  65.     register int fromx, fromy, tox, toy;
  66.  
  67.     if (dir==DOWN) {
  68.         r[x][y].doortable &= ~DOWN;
  69.         if (!r[x][y].real) {
  70.             fromx = r[x][y].rlx; fromy = r[x][y].rly;
  71.             fromx += 1 + 26*x; fromy += 7*y;
  72.         } else {
  73.             fromx = r[x][y].rlx + rn2(r[x][y].dx);
  74.             fromy = r[x][y].rly + r[x][y].dy;
  75.             fromx += 1 + 26*x; fromy += 7*y;
  76.             if (!IS_WALL(levl[fromx][fromy].typ))
  77.                 impossible("down: no wall at %d,%d?",fromx,
  78.                                     fromy);
  79.             dodoor(fromx, fromy, &rooms[r[x][y].nroom]);
  80.             levl[fromx][fromy].doormask = D_NODOOR;
  81.             mnewsym(fromx,fromy);
  82.             fromy++;
  83.         }
  84.         if(y >= 2) {
  85.             impossible("down door from %d,%d going nowhere?",x,y);
  86.             return;
  87.         }
  88.         y++;
  89.         r[x][y].doortable &= ~UP;
  90.         if (!r[x][y].real) {
  91.             tox = r[x][y].rlx; toy = r[x][y].rly;
  92.             tox += 1 + 26*x; toy += 7*y;
  93.         } else {
  94.             tox = r[x][y].rlx + rn2(r[x][y].dx);
  95.             toy = r[x][y].rly - 1;
  96.             tox += 1 + 26*x; toy += 7*y;
  97.             if (!IS_WALL(levl[tox][toy].typ))
  98.                 impossible("up: no wall at %d,%d?",tox,toy);
  99.             dodoor(tox, toy, &rooms[r[x][y].nroom]);
  100.             levl[tox][toy].doormask = D_NODOOR;
  101.             mnewsym(tox,toy);
  102.             toy--;
  103.         }
  104.         roguejoin(fromx, fromy, tox, toy, FALSE);
  105.         return;
  106.     } else if (dir == RIGHT) {
  107.         r[x][y].doortable &= ~RIGHT;
  108.         if (!r[x][y].real) {
  109.             fromx = r[x][y].rlx; fromy = r[x][y].rly;
  110.             fromx += 1 + 26*x; fromy += 7*y;
  111.         } else {
  112.             fromx = r[x][y].rlx + r[x][y].dx;
  113.             fromy = r[x][y].rly + rn2(r[x][y].dy);
  114.             fromx += 1 + 26*x; fromy += 7*y;
  115.             if (!IS_WALL(levl[fromx][fromy].typ))
  116.                 impossible("down: no wall at %d,%d?",fromx,
  117.                                     fromy);
  118.             dodoor(fromx, fromy, &rooms[r[x][y].nroom]);
  119.             levl[fromx][fromy].doormask = D_NODOOR;
  120.             mnewsym(fromx,fromy);
  121.             fromx++;
  122.         }
  123.         if(x >= 2) {
  124.             impossible("right door from %d,%d going nowhere?",x,y);
  125.             return;
  126.         }
  127.         x++;
  128.         r[x][y].doortable &= ~LEFT;
  129.         if (!r[x][y].real) {
  130.             tox = r[x][y].rlx; toy = r[x][y].rly;
  131.             tox += 1 + 26*x; toy += 7*y;
  132.         } else {
  133.             tox = r[x][y].rlx - 1;
  134.             toy = r[x][y].rly + rn2(r[x][y].dy);
  135.             tox += 1 + 26*x; toy += 7*y;
  136.             if (!IS_WALL(levl[tox][toy].typ))
  137.                 impossible("left: no wall at %d,%d?",tox,toy);
  138.             dodoor(tox, toy, &rooms[r[x][y].nroom]);
  139.             levl[tox][toy].doormask = D_NODOOR;
  140.             mnewsym(tox,toy);
  141.             tox--;
  142.         }
  143.         roguejoin(fromx, fromy, tox, toy, TRUE);
  144.         return;
  145.     } else impossible("corridor in direction %d?",dir);
  146. }
  147.             
  148. /* Modified walkfrom() from mkmaze.c */
  149. static
  150. void
  151. miniwalk(x, y)
  152. int x,y;
  153. {
  154.     register int q, dir;
  155.     int dirs[4];
  156.  
  157.     while(1) {
  158.         q = 0;
  159. #define doorhere (r[x][y].doortable)
  160.         if (x>0 && (!(doorhere & LEFT)) &&
  161.                     (!r[x-1][y].doortable || !rn2(10)))
  162.             dirs[q++] = 0;
  163.         if (x<2 && (!(doorhere & RIGHT)) &&
  164.                     (!r[x+1][y].doortable || !rn2(10)))
  165.             dirs[q++] = 1;
  166.         if (y>0 && (!(doorhere & UP)) &&
  167.                     (!r[x][y-1].doortable || !rn2(10)))
  168.             dirs[q++] = 2;
  169.         if (y<2 && (!(doorhere & DOWN)) &&
  170.                     (!r[x][y+1].doortable || !rn2(10)))
  171.             dirs[q++] = 3;
  172.     /* Rogue levels aren't just 3 by 3 mazes; they have some extra
  173.      * connections, thus that 1/10 chance
  174.      */
  175.         if (!q) return;
  176.         dir = dirs[rn2(q)];
  177.         switch(dir) { /* Move in direction */
  178.             case 0: doorhere |= LEFT;
  179.                 x--;
  180.                 doorhere |= RIGHT;
  181.                 break;
  182.             case 1: doorhere |= RIGHT;
  183.                 x++;
  184.                 doorhere |= LEFT;
  185.                 break;
  186.             case 2: doorhere |= UP;
  187.                 y--;
  188.                 doorhere |= DOWN;
  189.                 break;
  190.             case 3: doorhere |= DOWN;
  191.                 y++;
  192.                 doorhere |= UP;
  193.                 break;
  194.         }
  195.         miniwalk(x,y);
  196.     }
  197. }
  198.  
  199. void
  200. makeroguerooms() {
  201.     register struct mkroom *croom;
  202.     register int x,y;
  203.     int x2, y2;
  204.     /* Rogue levels are structured 3 by 3, with each section containing
  205.      * a room or an intersection.  The minimum width is 2 each way.
  206.      * One difference between these and "real" Rogue levels: real Rogue
  207.      * uses 24 rows and NetHack only 23.  So we cheat a bit by making the
  208.      * second row of rooms not as deep.
  209.      *
  210.      * Each normal space has 6/7 rows and 25 columns in which a room may
  211.      * actually be placed.  Walls go from rows 0-5/6 and columns 0-24.
  212.      * Not counting walls, the room may go in
  213.      * rows 1-5 and columns 1-23 (numbering starting at 0).  A room
  214.      * coordinate of this type may be converted to a level coordinate
  215.      * by adding 1+28*x to the column, and 7*y to the row.  (The 1
  216.      * is because column 0 isn't used [we only use 1-78]).
  217.      * Room height may be 2-4 (2-5 on last row), length 2-23 (not
  218.      * counting walls)
  219.      */
  220. #define here r[x][y]
  221.  
  222.     nroom = 0;
  223.     for(y=0; y<3; y++) for(x=0; x<3; x++) {
  224.         /* Note: we want to insure at least 1 room.  So, if the
  225.          * first 8 are all dummies, force the last to be a room.
  226.          */
  227.         if (!rn2(5) && (nroom || (x<2 && y<2))) {
  228.             /* Arbitrary: dummy rooms may only go where real
  229.              * ones do.
  230.              */
  231.             here.real = FALSE;
  232.             here.rlx = rn1(22, 2);
  233.             here.rly = rn1((y==2)?4:3, 2);
  234.         } else {
  235.             here.real = TRUE;
  236.             here.dx = rn1(22, 2); /* 2-23 long, plus walls */
  237.             here.dy = rn1((y==2)?4:3, 2); /* 2-5 high, plus walls */
  238.  
  239.             /* boundaries of room floor */
  240.             here.rlx = rnd(23 - here.dx + 1);
  241.             here.rly = rnd(((y==2) ? 5 : 4)- here.dy + 1);
  242.             nroom++;
  243.         }
  244.         here.doortable = 0;
  245.     }
  246.     miniwalk(rn2(3), rn2(3));
  247.     nroom = 0;
  248.     for(y=0; y<3; y++) for(x=0; x<3; x++) {
  249.         if (here.real) { /* Make a room */
  250.             r[x][y].nroom = nroom;
  251.             croom = &rooms[nroom];
  252.             /* Illumination.  Strictly speaking, it should be lit
  253.              * only if above level 10, but since Rogue rooms are
  254.              * only encountered below level 10...
  255.              */
  256.             if (!rn2(7)) {
  257.                 for(x2 = 1+26*x+here.rlx-1;
  258.                     x2 <= 1+26*x+here.rlx+here.dx; x2++)
  259.                 for(y2 = 7*y+here.rly-1;
  260.                     y2 <= 7*y+here.rly+here.dy; y2++)
  261.                     levl[x2][y2].lit = 1;
  262.                 croom->rlit = 1;
  263.             } else croom->rlit = 0;
  264.             croom->lx = 1 + 26*x + here.rlx;
  265.             croom->ly = 7*y + here.rly;
  266.             croom->hx = 1 + 26*x + here.rlx + here.dx - 1;
  267.             croom->hy = 7*y + here.rly + here.dy - 1;
  268.             /* Walls, doors, and floors. */
  269. #define lowx croom->lx
  270. #define lowy croom->ly
  271. #define hix croom->hx
  272. #define hiy croom->hy
  273.             for(x2 = lowx-1; x2 <= hix+1; x2++)
  274.                 for(y2 = lowy-1; y2 <= hiy+1; y2 += (hiy-lowy+2)) {
  275.                 levl[x2][y2].scrsym = HWALL_SYM;
  276.                 levl[x2][y2].typ = HWALL;
  277.             }
  278.             for(x2 = lowx-1; x2 <= hix+1; x2 += (hix-lowx+2))
  279.                 for(y2 = lowy; y2 <= hiy; y2++) {
  280.                 levl[x2][y2].scrsym = VWALL_SYM;
  281.                 levl[x2][y2].typ = VWALL;
  282.             }
  283.             for(x2 = lowx; x2 <= hix; x2++)
  284.                 for(y2 = lowy; y2 <= hiy; y2++) {
  285.                 levl[x2][y2].scrsym = ROOM_SYM;
  286.                 levl[x2][y2].typ = ROOM;
  287.             }
  288.             levl[lowx-1][lowy-1].typ = TLCORNER;
  289.             levl[hix+1][lowy-1].typ = TRCORNER;
  290.             levl[lowx-1][hiy+1].typ = BLCORNER;
  291.             levl[hix+1][hiy+1].typ = BRCORNER;
  292.             levl[lowx-1][lowy-1].scrsym = TLCORN_SYM;
  293.             levl[hix+1][lowy-1].scrsym = TRCORN_SYM;
  294.             levl[lowx-1][hiy+1].scrsym = BLCORN_SYM;
  295.             levl[hix+1][hiy+1].scrsym = BRCORN_SYM;
  296.  
  297.             /* Misc. */
  298.             smeq[nroom] = nroom;
  299.             croom->rtype = OROOM;
  300.             croom++;
  301.             croom->hx = -1;
  302.             nroom++;
  303.         }
  304.     }
  305.  
  306.     /* Now, add connecting corridors. */
  307.     for(y=0; y<3; y++) for(x=0; x<3; x++) {
  308.         if (here.doortable & DOWN)
  309.             roguecorr(x, y, DOWN);
  310.         if (here.doortable & RIGHT)
  311.             roguecorr(x, y, RIGHT);
  312.         if (here.doortable & LEFT)
  313.             impossible ("left end of %d, %d never connected?",x,y);
  314.         if (here.doortable & UP)
  315.             impossible ("up end of %d, %d never connected?",x,y);
  316.     }
  317. }
  318.  
  319. void
  320. corr(x,y)
  321. int x, y;
  322. {
  323.     if (rn2(50)) {
  324.         levl[x][y].typ = CORR;
  325.         levl[x][y].scrsym = CORR_SYM;
  326.     } else {
  327.         levl[x][y].typ = SCORR;
  328.         levl[x][y].scrsym = ' ';    /* _not_ STONE_SYM */
  329.     }
  330. }
  331.  
  332. void
  333. makerogueghost()
  334. {
  335.     register struct monst *ghost;
  336.     struct obj *ghostobj;
  337.     struct mkroom *croom;
  338.     int x,y;
  339.  
  340.     if (!nroom) return; /* Should never happen */
  341.     croom = &rooms[rn2(nroom)];
  342.     x = somex(croom); y = somey(croom);
  343.     if (!(ghost = makemon(&mons[PM_GHOST], x, y)))
  344.         return;
  345.     ghost->msleep = 1;
  346.     Strcpy((char *)ghost->mextra, roguename());
  347.  
  348.     if (rn2(4)) {
  349.         ghostobj = mksobj_at(FOOD_RATION,x,y);
  350.         ghostobj->quan = rnd(7);
  351.         ghostobj->owt = weight(ghostobj);
  352.     }
  353.     if (rn2(2)) {
  354.         ghostobj = mksobj_at(MACE,x,y);
  355.         ghostobj->spe = rnd(3);
  356.         if (rn2(4)) curse(ghostobj);
  357.     } else {
  358.         ghostobj = mksobj_at(TWO_HANDED_SWORD,x,y);
  359.         ghostobj->spe = rnd(5) - 2;
  360.         if (rn2(4)) curse(ghostobj);
  361.     }
  362.     ghostobj = mksobj_at(BOW,x,y);
  363.     ghostobj->spe = 1;
  364.     if (rn2(4)) curse(ghostobj);
  365.  
  366.     ghostobj = mksobj_at(ARROW,x,y);
  367.     ghostobj->spe = 0;
  368.     ghostobj->quan = rn1(10,25);
  369.     ghostobj->owt = weight(ghostobj);
  370.     if (rn2(4)) curse(ghostobj);
  371.  
  372.     if (rn2(2)) {
  373.         ghostobj = mksobj_at(RING_MAIL,x,y);
  374.         ghostobj->spe = rn2(3);
  375.         if (!rn2(3)) ghostobj->rustfree = 1;
  376.         if (rn2(4)) curse(ghostobj);
  377.     } else {
  378.         ghostobj = mksobj_at(PLATE_MAIL,x,y);
  379.         ghostobj->spe = rnd(5) - 2;
  380.         if (!rn2(3)) ghostobj->rustfree = 1;
  381.         if (rn2(4)) curse(ghostobj);
  382.     }
  383.     if (rn2(2)) {
  384.         ghostobj = mksobj_at(AMULET_OF_YENDOR,x,y);
  385.         ghostobj->spe = -1;
  386.         ghostobj->known = TRUE;
  387.     }
  388. }
  389. #endif /* REINCARNATION /**/
  390.